package com.tee.live.im.core.server.starter;


import com.tee.live.im.core.server.common.ChannelHandlerContextCache;
import com.tee.live.im.core.server.common.ImMsgDecode;
import com.tee.live.im.core.server.common.ImMsgEncode;
import com.tee.live.im.core.server.handler.ImServerCoreHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/**
 * @author tee
 * @date 2025/10/24
 */
@Configuration
public class NettyImServerStarter implements InitializingBean {

    private static final Logger log = LoggerFactory.getLogger(NettyImServerStarter.class);
    // 指定监听端口
    @Value("${sy.im.port}")
    private int port;

    @Resource
    private Environment env;


    //基于netty启动一个java进程,绑定监听端口
    public void startApplication(int port) throws InterruptedException {

        //处理accept事件
        NioEventLoopGroup boosGroup = new NioEventLoopGroup();
        //处理read,write事件
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boosGroup, workGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        //netty初始化相关handler
        bootstrap.childHandler(new ChannelInitializer<>() {
            @Override
            protected void initChannel(Channel ch) throws Exception {
                //打印日志,方便观察
                log.info("child channel 初始化开始");
                ch.pipeline().addLast(new ImMsgDecode());
                ch.pipeline().addLast(new ImMsgEncode());
                ch.pipeline().addLast(new ImServerCoreHandler());
            }
        });
        String registryIp = env.getProperty("DUBBO_IP_TO_REGISTRY");
        String registryPort = env.getProperty("DUBBO_PORT_TO_REGISTRY");
        if (StringUtils.isEmpty(registryIp) || StringUtils.isEmpty(registryPort)) {
            throw new IllegalArgumentException("启动参数中的注册端口和注册ip不能为空");
        }
        ChannelHandlerContextCache.setServerIpAddress(registryIp + ":" + registryPort);


        //基于钩子函数,优雅关机
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }));
        ChannelFuture channelFuture = bootstrap.bind(port).sync();
        // 这里会同步阻塞主线程,实现服务长期开启
        log.info("服务启动成功,监听端口:{}", port);
        channelFuture.channel().closeFuture().sync();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Thread nettyServerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    startApplication(port);
                } catch (InterruptedException e) {
                    log.error("服务启动失败", e);
                    throw new RuntimeException(e);
                }
            }
        });
        nettyServerThread.setName("sy-live-im-server");
        nettyServerThread.start();

    }
}
